fn main() {
    // 1.闭包不可变借用
    let color = String::from("green");

    // 这个闭包打印'color'.它会立即借用(通过引用,'&') 'color'并将该借用和
    // 闭包存储在'print'变量中.'color'会一直保持被借用状态直到'print'离开作用域.

    // 'println!'只需传引用就能使用,而这个闭包捕获的也是变量的引用,因此无需
    // 进一步处理就可以使用'println!'打印出'color'.
    let print = || println!("Now, {} is printing!", color);
    //使用借用来调用闭包'color'
    print();
    // 'color'可再次被不可变引用,因为闭包只持有一个指向'color'的不可变引用。
    let _reborrow = &color;
    print();
    // 在最后使用'print'之后，移动或重新借用都是允许的
    let _color_moved = color; // 移动'color'  

    // 2.闭包可变借用
    let mut count = 0;
    // 这个闭包'count'值增加。要做到这点，它需要得到'&mut count'或者'count'的本身。
    // 但'&mut count'的要求没有那么严格，因为闭包不会改变'count'的所有权。
    // 'inc'前面需要加上'mut'，因为闭包里存储着一个'&mut' 变量。
    // 调用闭包时，该变量的变化就意味着闭包内部发生了变化。因此闭包需要是可变的
    let mut inc = || {
        count += 1;
        println!("count: {count}");
    };
    // 使用可变借用调用闭包
    inc();
    // 因为之后调用闭包，所以仍然可变借用'count'
    // 试图重新借用将导致错误
    // let _reborrow = &count;
    // ^试一试：将此行注释去掉
    inc();
    // 闭包不再借用'&mut count',因此可以重新借用
    let _count_reborrow = &mut count;

    // 3.闭包所有权
    // 闭包可以捕获其环境的所有权。
    use std::mem;
    // 不可复制类型(non-copy type)
    let movable = Box::new(3);
    // 'mem::drop'要求'T'类型本身，所以闭包将会捕获变量的值。
    // 在这种情况下，可复制类型将会复制给闭包，从而原始值不受影响。不可复制类型必须移动到闭包中
    // 因而'movable'的值将被移动到闭包中。 
    let consume = || {
        println!("movable: {movable:?}");
        mem::drop(movable);
    };
    // `consume` 被调用，`movable` 被移动到闭包中,只调用一次。
    consume();
    // consume();
    // ^试一试：将此行注释去掉 
    // let _reborrow = &movable;
    // ^试一试：将此行注释去掉
    // 闭包已经拿到movable的所有权，所以不能再使用movable

    // 4.闭包之move会强制闭包取得被捕获变量的所有权
    // `Vec`本身是不可复制的，因此它必须被移动到闭包中。
    let list = vec![1, 2, 3];
    let contains = move |l| list.contains(l);
    println!("contains(1): {}", contains(&1));
    println!("contains(4): {}", contains(&4));
    // println!("list: {:?}, len: {}", list, list.len());
    // ^试一试：将此行注释去掉,将导致编译错误，因为`list`已经被移动到闭包中了。

}
